package compare;

import java.util.ArrayList;
import java.util.Comparator;

import org.testng.Assert;
import org.testng.annotations.Test;
//import org.testng.annotations.Test;

/**
 *
 *
 * In short, there isn't much difference. They are both ends to similar means. In general implement comparable
 * for natural order, (natural order definition is obviously open to interpretation), and write a comparator
 * for other sorting(排序) or comparison(比较) needs.
 *
 *
 */
public class Compare1 {

    /**
     * Number 比较器
     * @param <T>
     * 关于泛型，声明的时候可以
     * T类型可以在实例变量使用，？类型可以在静态变量使用
     */
    static class NumberComparator<T extends Number & Comparable<Number>> implements Comparator<T> {


        public static NumberComparator INSTANCE_NO_GEN = new NumberComparator<>();

        /**
         * 不是静态的，可以使用T表示支持的类型
         */
        public NumberComparator<T> INSTANCE = new NumberComparator<>();

        /**
         * 静态的变量，
         */
        public static NumberComparator<? extends Number> STATIC_INSTANCE = new NumberComparator<>();

        /**
         * 静态变量，直接用通配符？表示类型
         */
        public static NumberComparator<?> STATIC_INSTANCE2 = new NumberComparator<>();

        @Override
        public int compare(T a, T b)  {
            return a.compareTo( b );
        }

        public int compare(Integer b, Integer a) {
            return a.compareTo(b);
        }
    }






    static class StringSizeComparator implements Comparator<String> {

        @Override public int compare(String o1, String o2) {
            return o1.length() - o2.length();
        }
    }

    @Test
    private void t1() {
        String s1 = "a";
        String s2 = "b";

        // String实现了Comparable接口，natural 顺序，a 在 b 的前面
        int i = s1.compareTo(s2);
        Assert.assertEquals(i, -1);
    }

    @Test
    private void t2() {
        String s1 = "a";
        String s2 = "bc";
        String s3 = "aaa";
        // 如果需要比较长度，就需要定制一个比较器Comparator
        StringSizeComparator comparator = new StringSizeComparator();
        int compare = comparator.compare(s1, s2);
        Assert.assertEquals(compare, -1);

        // s2的长度小于s3的长度
        int compare1 = comparator.compare(s2, s3);
        Assert.assertEquals(compare1, -1);

        var list = new ArrayList<String>();
        list.add(s1);
        list.add(s2);
        list.add(s3);
        list.sort(comparator);
        System.out.println(list);

        // Comparator有默认实现逆序排序，而且是是定制的排序的逆序，而非自然逆序，
        list.sort(comparator.reversed());
        System.out.println(list);

    }


    @Test
    private void t3() {
        Number n1 = 1;
        Number n2 = 0.3;
        Number n3 = 1L;

//        int compare = NumberComparator.INSTANCE.compare(n1, n2);
//
//        int compare2 = NumberComparator.INSTANCE.compare(n2, n1);

        // 哪个类型的数字在第一个参数的位置上，就会调用那个类型的compareTo方法
        int compare3 = NumberComparator.INSTANCE_NO_GEN.compare(n3, n2);

        System.out.println(compare3);

    }

    @Test
    private void t4() {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(0);
        list.add(9);
        list.add(7);
        list.add(8);
        list.add(-1);

        // 要求降序，需要调整入参的位置
        list.sort((a, b) -> NumberComparator.STATIC_INSTANCE.compare(b, a));

        System.out.println(list);

    }

    @Test
    private void t5() {
        ArrayList<Double> list = new ArrayList<>();
        list.add(1.2);
        list.add(0.9999);
        list.add(9.3);
        list.add(7.7);
        list.add(8.5);
        list.add(-1.12);

        // 要求降序，需要调整入参的位置
//        list.sort((a, b) -> NumberComparator.INSTANCE.compare(b, a));

        System.out.println(list);

    }

    @Test
    private void t6() {
        ArrayList<Double> list = new ArrayList<>();
        list.add(1.2);
        list.add(0.9999);
        list.add(9.3);
//        list.add(7.7);
//        list.add(8.5);
//        list.add(-1.12);

        list.sort((a, b) -> compare.NumberComparator.INSTANCE.compare(b, a));
        System.out.println(list);
        list.sort((a, b) -> compare.NumberComparator.INSTANCE.compare(a, b));
        System.out.println(list);
    }

    /**
     * 多重比较条件比较器
     */
    @Test
    private void t7() {
        String s1 = "a";
        String s2 = "bc";
        String s3 = "aaa";
        String s4 = "A";
        String s5 = "AB";
        String s6 = "aB";

        var list = new ArrayList<String>();
        list.add(s1);
        list.add(s2);
        list.add(s3);
        list.add(s4);
        list.add(s5);
        list.add(s6);

        System.out.println("原始数据 \n" + list);

        // 先根据字符长度排序，然后根据大小写（小写在前）排序
        Comparator<String> cmp = Comparator.comparingInt(String::length).thenComparing(String.CASE_INSENSITIVE_ORDER);

        list.sort(cmp);
        System.out.println("" + list);

        // 反转所有比较条件
        list.sort(cmp.reversed());
        System.out.println(list);

        // 先根据字符长度排序，然后根据大小写逆序（大写在前）排序
        Comparator<String> cmp2 = Comparator.comparingInt(String::length).thenComparing(String.CASE_INSENSITIVE_ORDER.reversed());
        list.sort(cmp2);
        System.out.println(list);

    }

}
